home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / getethers < prev    next >
Encoding:
Text File  |  1992-01-03  |  24.9 KB  |  1,162 lines

  1. Newsgroups: comp.sources.unix
  2. From: davy@ecn.purdue.edu (Dave Curry)
  3. Subject: v25i092: getethers V1.0 - scan an ethernet and learn hostname/ethernet pairings
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: davy@ecn.purdue.edu (Dave Curry)
  8. Posting-Number: Volume 25, Issue 92
  9. Archive-Name: getethers
  10.  
  11. This is GETETHERS Version 1.0.                November, 1991
  12.  
  13. GETETHERS runs through all the addresses on an ethernet (a.b.c.1 - a.b.c.254)
  14. and pings each address, and then determines the ethernet address for that host.
  15. It produces a list, either in ASCII or in the binary format for an Excelan
  16. Lanalyzer, of hostname/ethernet address pairs for all hosts on that network.
  17.  
  18. This program has been tested on Sun workstations under SunOS 4.1.1.  It may
  19. work on other systems with minor modifications, but I don't need it anywhere
  20. else, and haven't tried.  It could be easily modified to generate files for
  21. other ethernet analyzer products (e.g., Sniffer), but since we don't have
  22. any of those, I don't feel real motivated to do it.
  23.  
  24. If you make modifications or fixes, please send them to me for incorporation
  25. into future versions.
  26.  
  27. Dave Curry
  28. Purdue University
  29. Engineering Computer Network
  30. davy@ecn.purdue.edu
  31.  
  32. #! /bin/sh
  33. # This is a shell archive, meaning:
  34. # 1. Remove everything above the #! /bin/sh line.
  35. # 2. Save the resulting text in a file.
  36. # 3. Execute the file with /bin/sh (not csh) to create the files:
  37. #    getethers
  38. # This archive created: Wed Nov 27 10:57:56 1991
  39. export PATH; PATH=/bin:$PATH
  40. if test ! -d 'getethers'
  41. then
  42.     echo shar: creating directory "'getethers'"
  43.     mkdir 'getethers'
  44. fi
  45. echo shar: entering directory "'getethers'"
  46. cd 'getethers'
  47. echo shar: extracting "'main.c'" '(3986 characters)'
  48. if test -f 'main.c'
  49. then
  50.     echo shar: will not over-write existing file "'main.c'"
  51. else
  52. sed 's/^X//' << \SHAR_EOF > 'main.c'
  53. X#ifndef lint
  54. Xstatic char *RCSid = "$Header: /usr/src/ecn/getethers/RCS/main.c,v 1.1 91/11/27 10:56:32 davy Exp $";
  55. X#endif
  56. X/*
  57. X * getethers - get hostname/ethernet address information for all hosts on
  58. X *           an ethernet.
  59. X *
  60. X * David A. Curry
  61. X * Purdue University
  62. X * Engineering Computer Network
  63. X * davy@ecn.purdue.edu
  64. X * November, 1991
  65. X *
  66. X * $Log:    main.c,v $
  67. X * Revision 1.1  91/11/27  10:56:32  davy
  68. X * Initial revision
  69. X * 
  70. X */
  71. X#include <sys/param.h>
  72. X#include <sys/socket.h>
  73. X#include <netinet/in.h>
  74. X#include <arpa/inet.h>
  75. X#include <string.h>
  76. X#include <netdb.h>
  77. X#include <stdio.h>
  78. X#include "defs.h"
  79. X
  80. Xchar    *pname;
  81. X
  82. Xmain(argc, argv)
  83. Xchar **argv;
  84. Xint argc;
  85. X{
  86. X    char *p;
  87. X    FILE *fp;
  88. X    u_long network;
  89. X    char *get_arp();
  90. X    struct hostent *hp;
  91. X    struct in_addr addr;
  92. X    HostInfo hosts[MAXHOST];
  93. X    char hname[64], fname[BUFSIZ];
  94. X    int lna, verbose, writefile;
  95. X
  96. X    pname = *argv;
  97. X    verbose = writefile = 0;
  98. X
  99. X    if (argc < 2)
  100. X        usage();
  101. X
  102. X    /*
  103. X     * Get our hostname.
  104. X     */
  105. X    if (gethostname(hname, sizeof(hname)) < 0) {
  106. X        error("gethostname");
  107. X        exit(1);
  108. X    }
  109. X
  110. X    /*
  111. X     * Process arguments.
  112. X     */
  113. X    while (--argc) {
  114. X        /*
  115. X         * Option.
  116. X         */
  117. X        if (**++argv == '-') {
  118. X            switch (*++*argv) {
  119. X            case 'v':            /* verbose    */
  120. X                verbose = 1;
  121. X                break;
  122. X            case 'w':            /* write files    */
  123. X                writefile = 1;
  124. X                break;
  125. X            default:
  126. X                usage();
  127. X                break;
  128. X            }
  129. X
  130. X            continue;
  131. X        }
  132. X
  133. X        /*
  134. X         * Do *something*.
  135. X         */
  136. X        if (!verbose && !writefile)
  137. X            verbose = 1;
  138. X
  139. X        /*
  140. X         * Convert the given network address to an internet
  141. X         * address.
  142. X         */
  143. X        network = inet_network(*argv);
  144. X        addr = inet_makeaddr(network, 0);
  145. X        bzero(hosts, sizeof(hosts));
  146. X
  147. X        /*
  148. X         * Find the ethernet interface that's on that network.
  149. X         */
  150. X        if ((lna = check_if(addr, hosts)) < 0) {
  151. X            fprintf(stderr, "%s: this host is not on the %s net.\n",
  152. X                pname, inet_ntoa(addr));
  153. X            continue;
  154. X        }
  155. X
  156. X        /*
  157. X         * Save our hostname.  check_if() filled in our
  158. X         * internet address and ethernet address.
  159. X         */
  160. X        hosts[lna].hl_name = hname;
  161. X
  162. X        if (verbose)
  163. X            printf("%s:\n    ", *argv);
  164. X
  165. X        /*
  166. X         * For each host...
  167. X         */
  168. X        for (lna = MINADDR; lna <= MAXADDR; lna++) {
  169. X            if ((verbose == 1) && ((lna % 16) == 0)) {
  170. X                printf("%d...", lna);
  171. X                fflush(stdout);
  172. X            }
  173. X
  174. X            /*
  175. X             * Skip our entry; we did it already.
  176. X             */
  177. X            if (hosts[lna].hl_name != NULL)
  178. X                continue;
  179. X
  180. X            /*
  181. X             * Build the internet address.
  182. X             */
  183. X            addr = inet_makeaddr(network, lna);
  184. X
  185. X            /*
  186. X             * Ping it, and if it's up...
  187. X             */
  188. X            if (ping(addr, lna)) {
  189. X                /*
  190. X                 * Get the hostname.
  191. X                 */
  192. X                hp = gethostbyaddr(&addr.s_addr,
  193. X                           sizeof(addr.s_addr),
  194. X                           AF_INET);
  195. X
  196. X                /*
  197. X                 * Save the hostname.
  198. X                 */
  199. X                if (hp != NULL)
  200. X                    hosts[lna].hl_name = strdup(hp->h_name);
  201. X                else
  202. X                    hosts[lna].hl_name = strdup("???");
  203. X
  204. X                /*
  205. X                 * Save the internet address and get the
  206. X                 * ethernet address from the arp table.
  207. X                 */
  208. X                hosts[lna].hl_inet = strdup(inet_ntoa(addr));
  209. X                hosts[lna].hl_ether = get_arp(addr);
  210. X            }
  211. X        }
  212. X
  213. X        if (verbose)
  214. X            putchar('\n');
  215. X
  216. X        /*
  217. X         * If we need to write files, create the file for this
  218. X         * network.
  219. X         */
  220. X        if (writefile) {
  221. X            p = strrchr(*argv, '.') + 1;
  222. X            sprintf(fname, "%snet.nam", p);
  223. X
  224. X            if ((fp = fopen(fname, "w")) == NULL) {
  225. X                error(fname);
  226. X                exit(1);
  227. X            }
  228. X
  229. X            excelan_header(fp);
  230. X        }
  231. X            
  232. X        /*
  233. X         * Write or print each entry.
  234. X         */
  235. X        for (lna = MINADDR; lna <= MAXADDR; lna++) {
  236. X            if (hosts[lna].hl_name == NULL)
  237. X                continue;
  238. X
  239. X            if (writefile)
  240. X                excelan_entry(&hosts[lna], fp);
  241. X                
  242. X            if (verbose) {
  243. X                printf("%s %s %s\n", hosts[lna].hl_name,
  244. X                       hosts[lna].hl_inet, hosts[lna].hl_ether);
  245. X            }
  246. X
  247. X            free(hosts[lna].hl_name);
  248. X            free(hosts[lna].hl_inet);
  249. X            free(hosts[lna].hl_ether);
  250. X        }
  251. X
  252. X        /*
  253. X         * Write a footer and close the file.
  254. X         */
  255. X        if (writefile) {
  256. X            excelan_footer(fp);
  257. X            fclose(fp);
  258. X        }
  259. X    }
  260. X
  261. X    exit(0);
  262. X}
  263. X
  264. X/*
  265. X * error - perror with program name.
  266. X */
  267. Xerror(s)
  268. Xchar *s;
  269. X{
  270. X    fprintf(stderr, "%s: ", pname);
  271. X    perror(s);
  272. X}
  273. X
  274. Xusage()
  275. X{
  276. X    fprintf(stderr, "Usage: %s [-v] [-w] network [network...]\n", pname);
  277. X    exit(1);
  278. X}
  279. SHAR_EOF
  280. if test 3986 -ne "`wc -c < 'main.c'`"
  281. then
  282.     echo shar: error transmitting "'main.c'" '(should have been 3986 characters)'
  283. fi
  284. chmod +x 'main.c'
  285. fi # end of overwriting check
  286. echo shar: extracting "'Makefile'" '(658 characters)'
  287. if test -f 'Makefile'
  288. then
  289.     echo shar: will not over-write existing file "'Makefile'"
  290. else
  291. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  292. X#
  293. X# $Header: /usr/src/ecn/getethers/RCS/Makefile,v 1.1 91/11/27 10:56:07 davy Exp $
  294. X#
  295. X# Makefile for getethers.
  296. X#
  297. X# David A. Curry
  298. X# Purdue University
  299. X# Engineering Computer Network
  300. X# davy@ecn.purdue.edu
  301. X# November, 1991
  302. X#
  303. XBINDIR=    /usr/ecn/etc
  304. XMANDIR=    /usr/man/man8
  305. X
  306. XCFLAGS=    -O
  307. X
  308. XOBJS=    arp.o excelan.o if.o main.o ping.o
  309. X
  310. Xgetethers: $(OBJS)
  311. X    $(CC) -o getethers $(OBJS)
  312. X
  313. Xinstall: getethers
  314. X    install -c -s -m 4750 -o root -g wheel getethers $(BINDIR)/getethers
  315. X    install -c -m 644 getethers.8l $(MANDIR)/getethers.8l
  316. X
  317. Xclean:
  318. X    rm -f a.out core getethers *.o \#*
  319. X
  320. Xarp.o:        arp.c
  321. Xexcelan.o:    excelan.c defs.h
  322. Xmain.o:        main.c defs.h
  323. Xif.o:        if.c defs.h
  324. Xping.o:        ping.c
  325. SHAR_EOF
  326. if test 658 -ne "`wc -c < 'Makefile'`"
  327. then
  328.     echo shar: error transmitting "'Makefile'" '(should have been 658 characters)'
  329. fi
  330. chmod +x 'Makefile'
  331. fi # end of overwriting check
  332. echo shar: extracting "'defs.h'" '(892 characters)'
  333. if test -f 'defs.h'
  334. then
  335.     echo shar: will not over-write existing file "'defs.h'"
  336. else
  337. sed 's/^X//' << \SHAR_EOF > 'defs.h'
  338. X/*
  339. X * $Header: /usr/src/ecn/getethers/RCS/defs.h,v 1.1 91/11/27 10:56:28 davy Exp $
  340. X *
  341. X * Definitions for getethers.
  342. X *
  343. X * David A. Curry
  344. X * Purdue University
  345. X * Engineering Computer Network
  346. X * davy@ecn.purdue.edu
  347. X * November, 1991
  348. X *
  349. X * $Log:    defs.h,v $
  350. X * Revision 1.1  91/11/27  10:56:28  davy
  351. X * Initial revision
  352. X * 
  353. X */
  354. X#define VERSION        1.0
  355. X
  356. X#define MAXHOST        256        /* max number of hosts to check    */
  357. X#define MINADDR        1        /* minimum host number        */
  358. X#define MAXADDR        254        /* maximum host number        */
  359. X#define MAXPING        3        /* max number of pings to send    */
  360. X#define PACKWAIT    1        /* min time to wait for packet    */
  361. X#define MAXPACKET    4096        /* max packet size for ping    */
  362. X#define FILESIZE    2584        /* size of lanalyzer file    */
  363. X
  364. X/*
  365. X * Record for a host.
  366. X */
  367. Xtypedef struct {
  368. X    char    *hl_name;        /* host name            */
  369. X    char    *hl_inet;        /* internet address        */
  370. X    char    *hl_ether;        /* ethernet address        */
  371. X} HostInfo;
  372. SHAR_EOF
  373. if test 892 -ne "`wc -c < 'defs.h'`"
  374. then
  375.     echo shar: error transmitting "'defs.h'" '(should have been 892 characters)'
  376. fi
  377. chmod +x 'defs.h'
  378. fi # end of overwriting check
  379. echo shar: extracting "'if.c'" '(2932 characters)'
  380. if test -f 'if.c'
  381. then
  382.     echo shar: will not over-write existing file "'if.c'"
  383. else
  384. sed 's/^X//' << \SHAR_EOF > 'if.c'
  385. X#ifndef lint
  386. Xstatic char *RCSid = "$Header: /usr/src/ecn/getethers/RCS/if.c,v 1.1 91/11/27 10:56:31 davy Exp $";
  387. X#endif
  388. X
  389. X/*
  390. X * if.c - routines to check a system's ethernet interfaces.
  391. X *
  392. X * David A. Curry
  393. X * Purdue University
  394. X * Engineering Computer Network
  395. X * davy@ecn.purdue.edu
  396. X * November, 1991
  397. X *
  398. X * $Log:    if.c,v $
  399. X * Revision 1.1  91/11/27  10:56:31  davy
  400. X * Initial revision
  401. X * 
  402. X */
  403. X#include <sys/param.h>
  404. X#include <sys/socket.h>
  405. X#include <netinet/in.h>
  406. X#include <arpa/inet.h>
  407. X#include <sys/ioctl.h>
  408. X#include <sys/time.h>
  409. X#include <sys/file.h>
  410. X#include <net/if.h>
  411. X#include <net/nit_if.h>
  412. X#include <netinet/if_ether.h>
  413. X#include <string.h>
  414. X#include <stdio.h>
  415. X#include "defs.h"
  416. X
  417. X/*
  418. X * check_if - check our ethernet interfaces and find the one that's attached
  419. X *          to the network in addr.
  420. X */
  421. Xcheck_if(addr, hosts)
  422. Xstruct in_addr addr;
  423. XHostInfo *hosts;
  424. X{
  425. X    int n, s, lna;
  426. X    char buf[BUFSIZ];
  427. X    struct ifreq ifr;
  428. X    struct ifconf ifc;
  429. X    struct sockaddr *sad;
  430. X    struct sockaddr_in *sin;
  431. X    register struct ifreq *ifrp;
  432. X
  433. X    /*
  434. X     * Need a socket...
  435. X     */
  436. X    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  437. X        error("socket");
  438. X        return(-1);
  439. X    }
  440. X
  441. X    ifc.ifc_buf = buf;
  442. X    ifc.ifc_len = sizeof(buf);
  443. X
  444. X    /*
  445. X     * Get the list of configured interfaces.
  446. X     */
  447. X    if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) {
  448. X        error("ioctl: SIOCGIFCONF");
  449. X        close(s);
  450. X
  451. X        return(-1);
  452. X    }
  453. X
  454. X    close(s);
  455. X
  456. X    /*
  457. X     * For each interface...
  458. X     */
  459. X    ifrp = ifc.ifc_req;
  460. X    for (n = ifc.ifc_len/sizeof(struct ifreq); n > 0; n--, ifrp++) {
  461. X        bcopy((char *) ifrp, (char *) &ifr, sizeof(struct ifreq));
  462. X
  463. X        /*
  464. X         * Need a new socket.
  465. X         */
  466. X        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  467. X            error("socket");
  468. X            return(-1);
  469. X        }
  470. X
  471. X        /*
  472. X         * Get the address of this interface.
  473. X         */
  474. X        if (ioctl(s, SIOCGIFADDR, (char *) &ifr) < 0) {
  475. X            error("ioctl: SIOCGIFADDR");
  476. X            close(s);
  477. X            
  478. X            return(-1);
  479. X        }
  480. X
  481. X        close(s);
  482. X
  483. X        sin = (struct sockaddr_in *) &ifr.ifr_addr;
  484. X
  485. X        /*
  486. X         * If it's not the one we need, bag it.
  487. X         */
  488. X        if ((sin->sin_addr.s_addr & addr.s_addr) != addr.s_addr)
  489. X            continue;
  490. X
  491. X        /*
  492. X         * Save the internet address, and keep the host byte.
  493. X         * We are assuming a netmask of 255.255.255.0 here.
  494. X         */
  495. X        lna = inet_lnaof(sin->sin_addr) & 0xff;
  496. X        hosts[lna].hl_inet = strdup(inet_ntoa(sin->sin_addr));
  497. X
  498. X        /*
  499. X         * Now we need the NIT, to get the ethernet address.
  500. X         */
  501. X        if ((s = open("/dev/nit", O_RDONLY)) < 0) {
  502. X            error("open: /dev/nit");
  503. X            return(-1);
  504. X        }
  505. X
  506. X        /*
  507. X         * Bind the nit to this interface.
  508. X         */
  509. X        if (ioctl(s, NIOCBIND, (char *) ifrp) < 0) {
  510. X            error("ioctl: NIOCBIND");
  511. X            close(s);
  512. X
  513. X            return(-1);
  514. X        }
  515. X
  516. X        /*
  517. X         * Get the address.
  518. X         */
  519. X        if (ioctl(s, SIOCGIFADDR, (char *) ifrp) < 0) {
  520. X            error("ioctl: SIOCGIFADDR");
  521. X            close(s);
  522. X
  523. X            return(-1);
  524. X        }
  525. X
  526. X        close(s);
  527. X
  528. X        /*
  529. X         * Save the ethernet address.
  530. X         */
  531. X        sad = (struct sockaddr *) &ifrp->ifr_addr;
  532. X        hosts[lna].hl_ether = strdup(ether_ntoa((struct ether_addr *)
  533. X                            sad->sa_data));
  534. X
  535. X        return(lna);
  536. X    }
  537. X
  538. X    return(-1);
  539. X}
  540. SHAR_EOF
  541. if test 2932 -ne "`wc -c < 'if.c'`"
  542. then
  543.     echo shar: error transmitting "'if.c'" '(should have been 2932 characters)'
  544. fi
  545. chmod +x 'if.c'
  546. fi # end of overwriting check
  547. echo shar: extracting "'ping.c'" '(4113 characters)'
  548. if test -f 'ping.c'
  549. then
  550.     echo shar: will not over-write existing file "'ping.c'"
  551. else
  552. sed 's/^X//' << \SHAR_EOF > 'ping.c'
  553. X#ifndef lint
  554. Xstatic char *RCSid = "$Header: /usr/src/ecn/getethers/RCS/ping.c,v 1.1 91/11/27 10:56:33 davy Exp $";
  555. X#endif
  556. X
  557. X/*
  558. X * ping.c - routines for pinging a host.
  559. X *
  560. X * David A. Curry
  561. X * Purdue University
  562. X * Engineering Computer Network
  563. X * davy@ecn.purdue.edu
  564. X * November, 1991
  565. X *
  566. X * $Log:    ping.c,v $
  567. X * Revision 1.1  91/11/27  10:56:33  davy
  568. X * Initial revision
  569. X * 
  570. X */
  571. X#include <sys/param.h>
  572. X#include <sys/socket.h>
  573. X#include <sys/file.h>
  574. X#include <netinet/in_systm.h>
  575. X#include <netinet/in.h>
  576. X#include <netinet/ip.h>
  577. X#include <netinet/ip_icmp.h>
  578. X#include <signal.h>
  579. X#include <setjmp.h>
  580. X#include <netdb.h>
  581. X#include <errno.h>
  582. X#include <stdio.h>
  583. X#include "defs.h"
  584. X
  585. Xstatic jmp_buf    env;
  586. Xstatic int    ident;
  587. Xstatic int    datalen = 64 - 8;
  588. Xstatic u_char    inpacket[MAXPACKET], outpacket[MAXPACKET];
  589. X
  590. X/*
  591. X * ping - send ICMP ECHO REQUEST packets to the host at addr until it either
  592. X *      responds or we decide to bag it.  Most of this code was stolen and
  593. X *      simplified from Mike Muuss' ping program.
  594. X */
  595. Xping(addr, id)
  596. Xstruct in_addr addr;
  597. Xint id;
  598. X{
  599. X    int ringring();
  600. X    register int i, n, s;
  601. X    int cc, hlen, fromlen;
  602. X    register u_char *datap;
  603. X    register struct ip *ip;
  604. X    register struct icmp *icp;
  605. X    struct sockaddr_in from, to;
  606. X    static struct protoent *proto = NULL;
  607. X
  608. X    bzero((char *) &to, sizeof(struct in_addr));
  609. X
  610. X    /*
  611. X     * Construct destination address.
  612. X     */
  613. X    to.sin_family = AF_INET;
  614. X    bcopy((char *) &addr, (char *) &to.sin_addr, sizeof(struct in_addr));
  615. X
  616. X    /*
  617. X     * ICMP ID number.
  618. X     */
  619. X    ident = (getpid() + id) & 0xFFFF;
  620. X
  621. X    /*
  622. X     * Look up protocol number.
  623. X     */
  624. X    if (proto == NULL) {
  625. X        if ((proto = getprotobyname("icmp")) == NULL) {
  626. X            error("icmp: unknown protocol");
  627. X            return(0);
  628. X        }
  629. X    }
  630. X
  631. X    /*
  632. X     * Need a raw socket.
  633. X     */
  634. X    if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
  635. X        error("socket");
  636. X        return(0);
  637. X    }
  638. X
  639. X    icp = (struct icmp *) outpacket;
  640. X
  641. X    /*
  642. X     * Send up to MAXPING packets.
  643. X     */
  644. X    for (i=0; i < MAXPING; i++) {
  645. X        /*
  646. X         * Construct ICMP header.
  647. X         */
  648. X        icp->icmp_type = ICMP_ECHO;
  649. X        icp->icmp_code = 0;
  650. X        icp->icmp_cksum = 0;
  651. X        icp->icmp_seq = i;
  652. X        icp->icmp_id = ident;
  653. X
  654. X        /*
  655. X         * Stick some junk in the packet.
  656. X         */
  657. X        cc = datalen + 8;
  658. X        datap = &outpacket[8];
  659. X
  660. X        for (n = 0; n < datalen; n++)
  661. X            *datap++ = n;
  662. X
  663. X        /*
  664. X         * Compute the IP checksum.
  665. X         */
  666. X        icp->icmp_cksum = in_cksum(icp, cc);
  667. X
  668. X        /*
  669. X         * Send the packet...
  670. X         */
  671. X        n = sendto(s, outpacket, cc, 0, &to, sizeof(struct sockaddr));
  672. X
  673. X        if ((n < 0) || (n != cc)) {
  674. X            if (n < 0)
  675. X                error("sendto");
  676. X            else
  677. X                error("sendto truncated");
  678. X
  679. X            close(s);
  680. X            return(0);
  681. X        }
  682. X
  683. X        /*
  684. X         * We'll wait for PACKWAIT seconds for a response.
  685. X         */
  686. X        signal(SIGALRM, ringring);
  687. X        fromlen = sizeof(struct sockaddr_in);
  688. X
  689. X        alarm(PACKWAIT);
  690. X
  691. X        /*
  692. X         * Bag it... send the next packet.
  693. X         */
  694. X        if (setjmp(env))
  695. X            continue;
  696. X
  697. X        /*
  698. X         * Get the packet.
  699. X         */
  700. X        cc = recvfrom(s, inpacket, MAXPACKET, 0, &from, &fromlen);
  701. X        alarm(0);
  702. X
  703. X        if (cc < 0) {
  704. X            if (errno == EINTR)
  705. X                continue;
  706. X
  707. X            error("recvfrom");
  708. X            continue;
  709. X        }
  710. X
  711. X        /*
  712. X         * Make sure it's a reply to ours.
  713. X         */
  714. X        ip = (struct ip *) inpacket;
  715. X        hlen = ip->ip_hl << 2;
  716. X
  717. X        if (cc < (hlen + ICMP_MINLEN))
  718. X            continue;
  719. X
  720. X        cc -= hlen;
  721. X        icp = (struct icmp *) (&inpacket[hlen]);
  722. X
  723. X        if (icp->icmp_type != ICMP_ECHOREPLY)
  724. X            continue;
  725. X
  726. X        if (icp->icmp_id != ident)
  727. X            continue;
  728. X
  729. X        /*
  730. X         * Yay!  The host is up.
  731. X         */
  732. X        close(s);
  733. X        return(1);
  734. X    }
  735. X
  736. X    /*
  737. X     * Boo!  The host is down.
  738. X     */
  739. X    close(s);
  740. X    return(0);
  741. X}
  742. X
  743. X/*
  744. X * in_cksum - compute the IP checksum.
  745. X */
  746. Xin_cksum(addr, len)
  747. Xu_short *addr;
  748. Xint len;
  749. X{
  750. X    register u_short *w = addr;
  751. X    register int nleft = len;
  752. X    register u_short answer;
  753. X    register int sum = 0;
  754. X
  755. X    /*
  756. X     * Use a 32-bit accumulator (sum) and add sequential 16-bit
  757. X     * words to it, then fold back all the carry bits from the
  758. X     * top 16 bits into the lower 16 bits.
  759. X     */
  760. X    while (nleft > 1) {
  761. X        sum += *w++;
  762. X        nleft -= 2;
  763. X    }
  764. X
  765. X    /*
  766. X     * Pick up odd byte if necessary.
  767. X     */
  768. X    if (nleft == 1)
  769. X        sum += *(u_char *) w;
  770. X
  771. X    /*
  772. X     * Add back the carry bits.
  773. X     */
  774. X    sum = (sum >> 16) + (sum & 0xFFFF);
  775. X    sum += (sum >> 16);
  776. X
  777. X    /*
  778. X     * Truncate to 16 bits.
  779. X     */
  780. X    answer = ~sum;
  781. X
  782. X    return(answer);
  783. X}
  784. X
  785. Xringring()
  786. X{
  787. X    longjmp(env, 1);
  788. X}
  789. SHAR_EOF
  790. if test 4113 -ne "`wc -c < 'ping.c'`"
  791. then
  792.     echo shar: error transmitting "'ping.c'" '(should have been 4113 characters)'
  793. fi
  794. chmod +x 'ping.c'
  795. fi # end of overwriting check
  796. echo shar: extracting "'arp.c'" '(1817 characters)'
  797. if test -f 'arp.c'
  798. then
  799.     echo shar: will not over-write existing file "'arp.c'"
  800. else
  801. sed 's/^X//' << \SHAR_EOF > 'arp.c'
  802. X#ifndef lint
  803. Xstatic char *RCSid = "$Header: /usr/src/ecn/getethers/RCS/arp.c,v 1.1 91/11/27 10:56:13 davy Exp $";
  804. X#endif
  805. X
  806. X/*
  807. X * arp.c - routines for digging up arp table entries.
  808. X *
  809. X * David A. Curry
  810. X * Purdue University
  811. X * Engineering Computer Network
  812. X * davy@ecn.purdue.edu
  813. X * November, 1991
  814. X *
  815. X * $Log:    arp.c,v $
  816. X * Revision 1.1  91/11/27  10:56:13  davy
  817. X * Initial revision
  818. X * 
  819. X */
  820. X#include <sys/param.h>
  821. X#include <sys/socket.h>
  822. X#include <netinet/in.h>
  823. X#include <sys/ioctl.h>
  824. X#include <net/if.h>
  825. X#include <net/if_arp.h>
  826. X#include <netinet/if_ether.h>
  827. X#include <string.h>
  828. X#include <errno.h>
  829. X#include <stdio.h>
  830. X
  831. Xextern int errno;
  832. X
  833. X/*
  834. X * get_arp - get the arp table entry for the internet address in addr, and
  835. X *         return the ethernet address as a character string.
  836. X */
  837. Xchar *
  838. Xget_arp(addr)
  839. Xstruct in_addr addr;
  840. X{
  841. X    int s;
  842. X    struct arpreq ar;
  843. X    char *ether_ntoa();
  844. X    struct sockaddr_in *sin;
  845. X
  846. X    /*
  847. X     * Clear the structure.
  848. X     */
  849. X    bzero((char *) &ar, sizeof(struct arpreq));
  850. X
  851. X    /*
  852. X     * We want internet family only.
  853. X     */
  854. X    ar.arp_pa.sa_family = AF_INET;
  855. X    sin = (struct sockaddr_in *) &ar.arp_pa;
  856. X
  857. X    /*
  858. X     * Copy in the internet address.
  859. X     */
  860. X    sin->sin_family = AF_INET;
  861. X    bcopy((char *) &addr, (char *) &sin->sin_addr, sizeof(struct sockaddr_in));
  862. X
  863. X    /*
  864. X     * Get a socket.
  865. X     */
  866. X    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  867. X        error("socket");
  868. X        return(strdup("(unknown)"));
  869. X    }
  870. X
  871. X    /*
  872. X     * Get the arp table entry.
  873. X     */
  874. X    if (ioctl(s, SIOCGARP, (char *) &ar) < 0) {
  875. X        /*
  876. X         * Nothing in the table.
  877. X         */
  878. X        if (errno == ENXIO) {
  879. X            close(s);
  880. X            return(strdup("(no entry)"));
  881. X        }
  882. X
  883. X        error("ioctl: SIOCGARP");
  884. X        close(s);
  885. X
  886. X        return("(unknown)");
  887. X    }
  888. X
  889. X    close(s);
  890. X
  891. X    /*
  892. X     * Is the entry complete?
  893. X     */
  894. X    if (ar.arp_flags & ATF_COM)
  895. X        return(strdup(ether_ntoa((struct ether_addr *) ar.arp_ha.sa_data)));
  896. X
  897. X    return(strdup("(incomplete)"));
  898. X}
  899. SHAR_EOF
  900. if test 1817 -ne "`wc -c < 'arp.c'`"
  901. then
  902.     echo shar: error transmitting "'arp.c'" '(should have been 1817 characters)'
  903. fi
  904. chmod +x 'arp.c'
  905. fi # end of overwriting check
  906. echo shar: extracting "'README'" '(900 characters)'
  907. if test -f 'README'
  908. then
  909.     echo shar: will not over-write existing file "'README'"
  910. else
  911. sed 's/^X//' << \SHAR_EOF > 'README'
  912. X                            November, 1991
  913. X
  914. XThis is GETETHERS Version 1.0.
  915. X
  916. XGETETHERS runs through all the addresses on an ethernet (a.b.c.1 - a.b.c.254)
  917. Xand pings each address, and then determines the ethernet address for that host.
  918. XIt produces a list, either in ASCII or in the binary format for an Excelan
  919. XLanalyzer, of hostname/ethernet address pairs for all hosts on that network.
  920. X
  921. XThis program has been tested on Sun workstations under SunOS 4.1.1.  It may
  922. Xwork on other systems with minor modifications, but I don't need it anywhere
  923. Xelse, and haven't tried.  It could be easily modified to generate files for
  924. Xother ethernet analyzer products (e.g., Sniffer), but since we don't have
  925. Xany of those, I don't feel real motivated to do it.
  926. X
  927. XIf you make modifications or fixes, please send them to me for incorporation
  928. Xinto future versions.
  929. X
  930. XDave Curry
  931. XPurdue University
  932. XEngineering Computer Network
  933. Xdavy@ecn.purdue.edu
  934. SHAR_EOF
  935. if test 900 -ne "`wc -c < 'README'`"
  936. then
  937.     echo shar: error transmitting "'README'" '(should have been 900 characters)'
  938. fi
  939. chmod +x 'README'
  940. fi # end of overwriting check
  941. echo shar: extracting "'excelan.c'" '(1748 characters)'
  942. if test -f 'excelan.c'
  943. then
  944.     echo shar: will not over-write existing file "'excelan.c'"
  945. else
  946. sed 's/^X//' << \SHAR_EOF > 'excelan.c'
  947. X#ifndef lint
  948. Xstatic char *RCSid = "$Header: /usr/src/ecn/getethers/RCS/excelan.c,v 1.1 91/11/27 10:56:30 davy Exp $";
  949. X#endif
  950. X
  951. X/*
  952. X * excelan.c - routines to write lanalyzer files.
  953. X *
  954. X * David A. Curry
  955. X * Purdue University
  956. X * Engineering Computer Network
  957. X * davy@ecn.purdue.edu
  958. X * November, 1991
  959. X *
  960. X * $Log:    excelan.c,v $
  961. X * Revision 1.1  91/11/27  10:56:30  davy
  962. X * Initial revision
  963. X * 
  964. X */
  965. X#include <sys/param.h>
  966. X#include <sys/socket.h>
  967. X#include <net/if.h>
  968. X#include <netinet/in.h>
  969. X#include <netinet/if_ether.h>
  970. X#include <stdio.h>
  971. X#include "defs.h"
  972. X
  973. Xint nbytes;                /* number of bytes written    */
  974. X
  975. X/*
  976. X * excelan_header - put out the mysterious crap at the top of the file.
  977. X */
  978. Xexcelan_header(fp)
  979. XFILE *fp;
  980. X{
  981. X    int i;
  982. X
  983. X    fwrite(" \20L\0\01\01", 1, 6, fp);
  984. X    fwrite("Excelan host name file", 1, 22, fp);
  985. X
  986. X    for (i = 0; i < 52; i++)
  987. X        fputc('\0', fp);
  988. X
  989. X    fwrite("!\20\304\t", 1, 4, fp);
  990. X
  991. X    nbytes = 84;
  992. X}
  993. X
  994. X/*
  995. X * excelan_entry - write out an ethernet address/hostname pair.
  996. X */
  997. Xexcelan_entry(h, fp)
  998. XHostInfo *h;
  999. XFILE *fp;
  1000. X{
  1001. X    int i;
  1002. X    register char *p;
  1003. X    struct ether_addr *ea, *ether_aton();
  1004. X
  1005. X    /*
  1006. X     * Magic.
  1007. X     */
  1008. X    fputc('\31', fp);
  1009. X
  1010. X    /*
  1011. X     * Write the ethernet address.
  1012. X     */
  1013. X    ea = ether_aton(h->hl_ether);
  1014. X    fwrite(ea, 1, 6, fp);
  1015. X
  1016. X    /*
  1017. X     * Put the hostname.
  1018. X     */
  1019. X    for (i=0, p=h->hl_name; (i < 18) && (*p != '.'); i++, p++)
  1020. X        fputc(*p, fp);
  1021. X
  1022. X    /*
  1023. X     * Pad with nulls.
  1024. X     */
  1025. X    for (; i < 18; i++)
  1026. X        fputc('\0', fp);
  1027. X
  1028. X    nbytes += 25;
  1029. X}
  1030. X
  1031. X/*
  1032. X * excelan_footer - pad the file to FILESIZE bytes.
  1033. X */
  1034. Xexcelan_footer(fp)
  1035. XFILE *fp;
  1036. X{
  1037. X    /*
  1038. X     * Put out the broadcast address.
  1039. X     */
  1040. X    fputc('\31', fp);
  1041. X    fwrite("\377\377\377\377\377\377", 1, 6, fp);
  1042. X    fwrite("BROADCAST\0", 1, 10, fp);
  1043. X
  1044. X    nbytes += 17;
  1045. X
  1046. X    /*
  1047. X     * Pad the file.
  1048. X     */
  1049. X    for (; nbytes < FILESIZE; nbytes++)
  1050. X        fputc('\0', fp);
  1051. X}
  1052. SHAR_EOF
  1053. if test 1748 -ne "`wc -c < 'excelan.c'`"
  1054. then
  1055.     echo shar: error transmitting "'excelan.c'" '(should have been 1748 characters)'
  1056. fi
  1057. chmod +x 'excelan.c'
  1058. fi # end of overwriting check
  1059. echo shar: extracting "'getethers.8l'" '(2415 characters)'
  1060. if test -f 'getethers.8l'
  1061. then
  1062.     echo shar: will not over-write existing file "'getethers.8l'"
  1063. else
  1064. sed 's/^X//' << \SHAR_EOF > 'getethers.8l'
  1065. X.TH GETETHERS 8L "27 November 1991" "ECN"
  1066. X.SH NAME
  1067. Xgetethers \- get ethernet address/hostname information
  1068. X.SH SYNOPSIS
  1069. X.B getethers
  1070. X[
  1071. X.B \-v
  1072. X] [
  1073. X.B \-w
  1074. X]
  1075. X.I network
  1076. X[
  1077. X.IR network ...
  1078. X]
  1079. X.SH DESCRIPTION
  1080. X.PP
  1081. X.B getethers
  1082. Xprobes the specified network(s),
  1083. Xwhose addresses are given in Internet ``dot'' notation,
  1084. Xand produces a list of host name and ethernet address pairs for each host
  1085. Xon the network that responds to ICMP ECHO_REQUEST packets.
  1086. XThe program assumes a subnet mask of 255.255.255.0 (0xffffff00),
  1087. Xand does not probe host number 0 or host number 255,
  1088. Xwhich are used as the broadcast address.
  1089. X.PP
  1090. XIf the
  1091. X.B \-v
  1092. Xoption is specified,
  1093. Xa list is produced on the standard output that contains the host name,
  1094. Xinternet address,
  1095. Xand ethernet address of each host that responded to ICMP ECHO_REQUEST
  1096. Xpackets.
  1097. XIf the
  1098. X.B \-w
  1099. Xoption is specified,
  1100. Xa file will be written for each network that can be used with the Excelan
  1101. XLanalyzer product as a name-to-address translation file.
  1102. XThe name of the file will be
  1103. X.IR XXXnet.nam ,
  1104. Xwhere
  1105. X.I XXX
  1106. Xis the last byte of the network address.
  1107. X.PP
  1108. X.B getethers
  1109. Xworks by first probing the system's ethernet interfaces,
  1110. Xlooking for the interface that is connected to the specified network.
  1111. XIf the system is not connected to that network,
  1112. X.B getethers
  1113. Xprints an error message and goes on to the next network.
  1114. XAfter discovering the proper interface,
  1115. X.B getethers
  1116. Xsends up to three ICMP ECHO_REQUEST packets to each host number on that
  1117. Xnetwork from 1 to 254.
  1118. XIf the host responds,
  1119. X.B getethers
  1120. Xthen searches the local host's arp table for the remote host's ethernet
  1121. Xaddress.
  1122. XIf the remote host does not respond to the ECHO_REQUEST packets within
  1123. Xthree seconds,
  1124. Xit is assumed to be down or non-existent,
  1125. Xand is skipped.
  1126. X.SH SEE ALSO
  1127. X.BR arp (4P),
  1128. X.BR arp (8C),
  1129. X.BR etherfind (8C),
  1130. X.BR ethers (3N),
  1131. X.BR icmp (4P),
  1132. X.BR inet (3N),
  1133. X.BR nit (4P),
  1134. X.BR ping (8C),
  1135. X.BR rarpd (8C)
  1136. X.SH BUGS
  1137. X.PP
  1138. XThe assumption of a 255.255.255.0 subnet mask,
  1139. Xand the assumption of all-zero or all-ones as a broadcast address,
  1140. Xare probably not good ideas and should be determined at run-time,
  1141. Xbut it works in our environment.
  1142. X.PP
  1143. XThe Lanalyzer file,
  1144. Xdue to its fixed size,
  1145. Xcannot handle more than 100 entries.
  1146. XIf a network has more than 100 hosts connected (and up),
  1147. Xthe file will not be usable (or at least the stuff after 100 entries won't
  1148. Xbe).
  1149. X.SH AUTHOR
  1150. XDavid A. Curry, Purdue University Engineering Computer Network
  1151. SHAR_EOF
  1152. if test 2415 -ne "`wc -c < 'getethers.8l'`"
  1153. then
  1154.     echo shar: error transmitting "'getethers.8l'" '(should have been 2415 characters)'
  1155. fi
  1156. chmod +x 'getethers.8l'
  1157. fi # end of overwriting check
  1158. echo shar: done with directory "'getethers'"
  1159. cd ..
  1160. #    End of shell archive
  1161. exit 0
  1162.